package io.github.kouleen.minecraft.plugin.redpacket.entity;

import org.bukkit.entity.Player;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public class RedPacket {

    public enum RedPacketType {
        RANDOM,   // 随机金额
        FIXED     // 固定金额
    }

    private final String id;
    private final UUID uniqueId;
    private final String senderName;
    private final int totalAmount;
    private final int totalCount;
    private final String message;
    private final long expireTime;
    private final RedPacketType type;
    private final Set<UUID> claimedPlayers = new HashSet<>();
    private int remainingAmount;
    private int remainingCount;
    private final List<Integer> amounts;

    public RedPacket(UUID uniqueId, String senderName, int totalAmount, int totalCount, String message, long expireSeconds, RedPacketType type) {
        this.id = UUID.randomUUID().toString();
        this.uniqueId = uniqueId;
        this.senderName = senderName;
        this.totalAmount = totalAmount;
        this.totalCount = totalCount;
        this.message = message;
        this.expireTime = System.currentTimeMillis() + (expireSeconds * 1000);
        this.type = type;
        this.remainingAmount = totalAmount;
        this.remainingCount = totalCount;
        this.amounts = generateAmounts();
    }

    /**
     * 生成红包金额列表
     */
    private List<Integer> generateAmounts() {
        List<Integer> result = new ArrayList<>();

        if (type == RedPacketType.FIXED) {
            // 固定金额
            int fixedAmount = Math.round((totalAmount / totalCount) * 100) / 100;
            for (int i = 0; i < totalCount; i++) {
                // 最后一个红包处理可能的精度误差
                if (i == totalCount - 1) {
                    fixedAmount = totalAmount - (fixedAmount * (totalCount - 1));
                    fixedAmount = Math.round(fixedAmount * 100) / 100;
                }
                result.add(fixedAmount);
            }
        } else {
            // 随机金额（拼手气）
            int remaining = totalAmount;
            int remainingNum = totalCount;

            for (int i = 0; i < totalCount - 1; i++) {
                // 保证每个人至少能拿到0.01
                int min = 1;
                // 调整max计算方式，确保max始终大于min
                int max = remaining - (min * (remainingNum - 1));

                // 添加边界检查，确保max > min
                if (max <= min) {
                    max = min + 1; // 给一点额外空间
                }

                int amount = ThreadLocalRandom.current().nextInt(min, max);
                amount = Math.round(amount * 100) / 100;

                result.add(amount);
                remaining -= amount;
                remainingNum--;
            }

            // 最后一个红包拿剩余的所有金额
            result.add(Math.round(remaining * 100) / 100);
        }

        return result;
    }

    public UUID getUniqueId() {
        return uniqueId;
    }

    /**
     * 玩家领取红包
     */
    public int claim(Player player) {
        // 检查是否已领取
        if (claimedPlayers.contains(player.getUniqueId())) {
            return 0;
        }

        // 检查是否已领完
        if (remainingCount <= 0) {
            return 0;
        }

        // 记录领取者
        claimedPlayers.add(player.getUniqueId());

        // 减少剩余数量
        remainingCount--;

        // 获取领取金额
        int amount = amounts.get(totalCount - remainingCount - 1);
        remainingAmount -= amount;

        return amount;
    }

    /**
     * 检查红包是否已过期
     */
    public boolean isExpired() {
        return System.currentTimeMillis() > expireTime;
    }

    /**
     * 检查红包是否已领完
     */
    public boolean isEmpty() {
        return remainingCount <= 0;
    }

    // Getters
    public String getId() {
        return id;
    }

    public String getSender() {
        return senderName;
    }

    public double getTotalAmount() {
        return totalAmount;
    }

    public int getTotalCount() {
        return totalCount;
    }

    public String getMessage() {
        return message;
    }

    public long getExpireTime() {
        return expireTime;
    }

    public RedPacketType getType() {
        return type;
    }

    public int getRemainingAmount() {
        return remainingAmount;
    }

    public int getRemainingCount() {
        return remainingCount;
    }

    public Set<UUID> getClaimedPlayers() {
        return Collections.unmodifiableSet(claimedPlayers);
    }

    public List<Integer> getAmounts() {
        return amounts;
    }
}
